CS 5010: Problem Set 7

Out: Monday, February 29, 2016

Due: Monday, March 14, 2016 at 5pm.

The goal of this problem set is to give you practice using context arguments and invariants.

Remember that you must follow the design recipe, and write invariants (as WHERE clauses) whenever an argument represents context information.

You must use DrScheme's HtDP Intermediate Student Language with Lambda. Use list abstractions like filter, fold, and map whenever they are helpful. As before, you will be penalized for failing to use these when they are "obviously" applicable.

Not everything on this problem set requires the use of invariants; some may only require generalization. Part of your task is to figure out when you need an invariant and when you do not. Remember, it is the purpose statement that determines whether or not you need to state an invariant.

Remember you must follow the design recipe. Your deliverables include the data definitions (including interpretation and templates), contract and purpose header, strategies, code, and tests. Be sure to sync your work and fill out a Work Session Report at the end of every work session. Use the Work Session Report for PS07.

As usual, the rubric for grading is here.


Required Exercises

This problem set contains two separate problems. The first problem repeats the first problem of Problem Set 06, without the parts of the WHERE clauses that forbade cycles in the list of schedules. For the second problem, you will create a graphical user interface for creating and testing finite state machines.

For both of these problems, you should use HOFs whenever they improve your code.

  1. (trains-3). Repeat problem 1 from Problem Set 06, without the parts of the WHERE clauses that say "it is not possible to ride forever using the schedules given".
    (define adirondack
      (make-schedule
       "Adirondack"
       (list (make-brief-stop (make-train-time 10 20 "A") "Montreal, QC")
             (make-brief-stop (make-train-time  1 25 "P") "Plattsburgh, NY")
             (make-brief-stop (make-train-time  4 45 "P") "Saratoga Springs, NY")
             (make-stop       (make-train-time  5 57 "P")
                              (make-train-time  6 15 "P") "Albany, NY")
             (make-brief-stop (make-train-time  7 15 "P") "Poughkeepsie, NY")
             (make-brief-stop (make-train-time  8 50 "P") "New York, NY"))))
    
    (define adirondack-nb
      (make-schedule
       "Adirondack (northbound)"
       (list (make-brief-stop (make-train-time  8 15 "A") "New York, NY")
             (make-brief-stop (make-train-time  9 45 "A") "Poughkeepsie, NY")
             (make-stop       (make-train-time 10 50 "A")
                              (make-train-time 11 10 "A") "Albany, NY")
             (make-brief-stop (make-train-time 12 02 "P") "Saratoga Springs, NY")
             (make-brief-stop (make-train-time  3 22 "P") "Plattsburgh, NY")
             (make-brief-stop (make-train-time  7 11 "P") "Montreal, QC"))))
    
    (define empire-service
      (make-schedule
       "Empire Service"
       (list (make-brief-stop (make-train-time 12 05 "P") "Albany, NY")
             (make-brief-stop (make-train-time  1 10 "P") "Poughkeepsie, NY")
             (make-brief-stop (make-train-time  2 45 "P") "New York, NY"))))
    
    (define empire-service-nb
      (make-schedule
       "Empire Service (northbound)"
       (list (make-brief-stop (make-train-time  3 15 "P") "New York, NY")
             (make-brief-stop (make-train-time  4 40 "P") "Poughkeepsie, NY")
             (make-brief-stop (make-train-time  5 45 "P") "Albany, NY"))))
    
    (define ethan-allen-express
      (make-schedule
       "Ethan Allen Express"
       (list (make-brief-stop (make-train-time  8 00 "A") "Rutland, VT")
             (make-brief-stop (make-train-time  9 37 "A") "Saratoga Springs, NY")
             (make-stop       (make-train-time 10 50 "A")
                              (make-train-time 11 10 "A") "Albany, NY")
             (make-brief-stop (make-train-time 12 10 "P") "Poughkeepsie, NY")
             (make-brief-stop (make-train-time  1 45 "P") "New York, NY"))))
    
    (define ethan-allen-express-nb
      (make-schedule
       "Ethan Allen Express (northbound)"
       (list (make-brief-stop (make-train-time  3 15 "P") "New York, NY")
             (make-brief-stop (make-train-time  4 40 "P") "Poughkeepsie, NY")
             (make-stop       (make-train-time  5 45 "P")
                              (make-train-time  6 00 "P") "Albany, NY")
             (make-brief-stop (make-train-time  6 50 "P") "Saratoga Springs, NY")
             (make-brief-stop (make-train-time  8 48 "P") "Rutland, VT"))))
    
    (define those-six-trains
      (list adirondack          adirondack-nb
            empire-service      empire-service-nb
            ethan-allen-express ethan-allen-express-nb))
    
    (define those-same-six-trains
      (reverse those-six-trains))
    
    (trains-connect? those-six-trains
                     "Boston, MA" "New York, NY")                       ; => false
    (trains-connect? those-six-trains
                     "Plattsburgh, NY" "Rutland, VT")                   ; => true
    (trains-connect? those-same-six-trains
                     "Plattsburgh, NY" "Rutland, VT")                   ; => true
    (itinerary those-six-trains
               "Plattsburgh, NY" "Rutland, VT")
    ;;; =>
    ;;; (list
    ;;;  (make-schedule
    ;;;   "Adirondack"
    ;;;   (list
    ;;;    (make-brief-stop (make-train-time 1 25 "P") "Plattsburgh, NY")
    ;;;    (make-brief-stop (make-train-time 4 45 "P") "Saratoga Springs, NY")))
    ;;;  (make-schedule
    ;;;   "Ethan Allen Express (northbound)"
    ;;;   (list
    ;;;    (make-brief-stop (make-train-time 6 50 "P") "Saratoga Springs, NY")
    ;;;    (make-brief-stop (make-train-time 8 48 "P") "Rutland, VT"))))
    
    (itinerary those-six-trains
               "Plattsburgh, NY" "Rutland, VT")
    ;;; => same abbreviated itinerary as above
    ;;;
    ;;; There are 636 ways to get from Plattsburgh to Rutland
    ;;; using those six trains without taking any train twice,
    ;;; but that's the only way to do it in 443 minutes.
    
    (travel-time those-six-trains
                 "Plattsburgh, NY" "Rutland, VT")                        ; => 443
    
  2. (fsm-3). For this problem, you will deliver a file named fsm-3.rkt that implements a graphical user interface (GUI) for creating and testing finite state machines. That GUI is specified as follows:

    Example: The following scene was produced by

    demo for problem 2

    Here is an example of a finite state machine that accepts all binary numerals congruent to 3 mod 5:

    this machine accepts binary numerals congruent to 3 modulo 5

    Your fsm-3.rkt file must provide all thirteen functions provided by your fsm-2.rkt file in Problem Set 06, and must also provide the following nine functions:

    ;;; run : PosReal -> World
    ;;; GIVEN: the number of seconds per tick
    ;;; EFFECT: runs the GUI, starting with the initial state
    ;;;     returned by initial-world
    ;;; RETURNS: the final state of the world
    ;;; EXAMPLES:
    ;;;     (run 1)
    
    ;;; initial-world : Any -> World
    ;;; GIVEN: any value (ignored)
    ;;; RETURNS: the initial world specified for the GUI
    ;;; EXAMPLE: (initial-world 0)
    
    ;;; world-after-key-event : World KeyEvent -> WorldState
    ;;; GIVEN: a World and a KeyEvent
    ;;; RETURNS: the World that should follow the given World
    ;;;     after the given KeyEvent
    
    ;;; world-after-mouse-event : World Int Int MouseEvent -> World
    ;;; GIVEN: a World, the x- and y-coordinates of a mouse event, and the
    ;;;     mouse event
    ;;; RETURNS: the world that should follow the given world after the given
    ;;;     mouse event.
    
    ;;; world-machine : World -> ListOfMachineState
    ;;; GIVEN: a World
    ;;; RETURNS: the list of machine states being displayed in that world
    ;;;     (which might not be a machine as defined by is-machine?)
    ;;; EXAMPLE: (world-machine (initial-world 0)) => empty
    
    ;;; world-selected-states : World -> ListOfMachineState
    ;;; GIVEN: a World
    ;;; RETURNS: a list of the currently selected machine states
    
    ;;; world-with-selected-states : World ListOfMachineState -> World
    ;;; GIVEN: a world and a list containing some of its machine states
    ;;; WHERE: the list is a set (contains no duplicates)
    ;;; RETURNS: a world like the given world but with the given set
    ;;;     of machine states as its set of selected states
    ;;; EXAMPLE:
    ;;;     if q1 and q2 belong to (world-machine world), then
    ;;;     (world-selected-states
    ;;;      (world-with-selected-states world (list q1 q2)))
    ;;;     => (list q1 q2) or (list q2 q1)
    
    ;;; world-with-new-state : World String -> World
    ;;; GIVEN: a World and the name of a new state
    ;;; WHERE: no state in the world already has that name
    ;;; RETURNS: the world that should result from typing "N"
    ;;;     followed by the name of the new state, followed by "\r"
    ;;; EXAMPLE:
    ;;;     (world-machine
    ;;;      (world-with-new-state (initial-world 17) "q0"))
    ;;;  => (list (make-machine-state "q0" true false empty))
    
    ;;; world-with-new-transition :
    ;;;     World InputSymbol MachineState MachineState -> World
    ;;; GIVEN: a world, an input symbol, and machine states q1 and q2
    ;;; WHERE: q1 and q2 belong to (world-machine world),
    ;;;     and q1 doesn't already have a transition to q2 via the input symbol
    ;;; RETURNS: the world that should result from adding a transition
    ;;;     labelled by the given input symbol that takes q1 to q2
    

    Hint: The scene+curve function of 2htdp/image is useful when drawing edges of a graph. Open arrowheads can be drawn using line. Do not worry about drawing nicer-looking graphs until you have completed a first draft of your solution.


Last modified: Thu Mar 03 2016